#include <kew/c-vm.h>

int kew__initialized = 0;
char *kew__version = "";
GHashTable *kew__selectors;
GHashTable *kew__call_shapes;
KewThreadSystem kew_thread_system_single;
KewThreadContext kew__single_thread_context;

static KewThreadContext *current_context_single(void)
{
    return &kew__single_thread_context;
}

static void noop(void)
{
}

/*
 * Library initialization functions.
 */

void kew_init(void)
{
    /* NOTE: this has race conditions if called multi-threaded */
    if (! kew__initialized) {
        kew__version = VERSION;
        kew__selectors = g_hash_table_new(g_str_hash, g_str_equal);
        kew__call_shapes = g_hash_table_new(call_shape_hash, call_shape_equal);

        /* initialize support for single-threading thread context */
        kew__single_thread_context.top_ensured_stack_frame = NULL;
        kew__single_thread_context.top_call_frame = NULL;
        kew__single_thread_context.extensions = g_hash_table_new(g_ptr_hash, g_ptr_equal);

        kew_thread_system_single.current_context = &current_context_single;
        kew_thread_system_single.lock_selectors = &noop;
        kew_thread_system_single.unlock_selectors = &noop;
        kew_thread_system_single.lock_call_shapes = &noop;
        kew_thread_system_single.unlock_call_shapes = &noop;
        
        kew__thread_system = &kew_thread_system_single;
        
        kew__initialized = 1;
    }
}

char *kew_version(void)
{
    return kew__version;
}

void kew_thread_add_extension(gpointer key, gpointer value)
{
    g_hash_table_insert((*kew__thread_system->current_context)()->extensions, key, value);
}

void kew_thread_remove_extension(gpointer key)
{
    g_hash_table_remove((*kew__thread_system->current_context)()->extensions, key);
}

gpointer kew_thread_get_extension(gpointer key)
{
    return g_hash_table_lookup((*kew__thread_system->current_context)()->extensions, key);
}
